/*
 ------------------------------------------------------------------------------
 Copyright (C) 2013 Eternal Games.

 This file is part of the EternalTech source code.

 The EternalTech source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The EternalTech source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the EternalTech source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// r_decal.cpp - decal clipping and management
//


#include "r_local.h"


struct decalClip_t {
	int todo;
};


/*
 ==================
 R_AllocDecal
 ==================
*/
decal_t *R_AllocDecal (scene_t *scene){

	decal_t	*decal;

	// Allocate a slot, freeing the oldest if necessary
	if (!scene->freeDecal)
		R_FreeDecal(scene, scene->activeDecal.prev);

	decal = scene->freeDecal;

	scene->numDecals++;

	// Set up
	decal->active = true;

	// Link
	scene->freeDecal = scene->freeDecal->next;

	decal->prev = &scene->activeDecal;
	decal->next = scene->activeDecal.next;

	scene->activeDecal.next->prev = decal;
	scene->activeDecal.next = decal;

	return decal;
}

/*
 ==================
 R_FreeDecal
 ==================
*/
void R_FreeDecal (scene_t *scene, decal_t *decal){

	// Free the base indices if needed
	if (decal->baseIndices)
		Mem_Free(decal->baseIndices);

	// Free the indices and vertices
	Mem_Free(decal->indices);
	Mem_Free(decal->vertices);

	// No longer active
	decal->active = false;

	// Unlink
	decal->prev->next = decal->next;
	decal->next->prev = decal->prev;

	// Free the slot
	decal->next = scene->freeDecal;
	scene->freeDecal = decal;

	scene->numDecals--;
}

/*
 ==================
 
 ==================
*/
bool R_UpdateDecal (scene_t *scene, decal_t *decal){

	return true;
}


/*
 ==============================================================================

 DECAL CLIPPING

 ==============================================================================
*/


/*
 ==================
 
 ==================
*/
static void R_ClipSurfaceToDecal (scene_t *scene, decalClip_t *clip, surface_t *surface){

}

/*
 ==================
 
 ==================
*/
static void R_ClipWorldToDecal (scene_t *scene, decalClip_t *clip, node_t *node){

}

/*
 ==================
 
 ==================
*/
static void R_ClipInlineModelToDecal (scene_t *scene, decalClip_t *clip){

}

/*
 ==================
 
 ==================
*/
static void R_ClipAliasModelToDecal (scene_t *scene, decalClip_t *clip){

}


/*
 ==============================================================================

 WORLD & MODEL PROJECTION

 ==============================================================================
*/


/*
 ==================
 
 ==================
*/
void R_ProjectDecalOntoWorld (scene_t *scene, const glqVec3 &origin, const glqVec3 &direction, float rotation, float size, float depth, int startTime, material_t *material){

}

/*
 ==================
 R_RemoveDecalsFromWorld
 ==================
*/
void R_RemoveDecalsFromWorld (scene_t *scene){

	decal_t	*decal, *next;

	if (scene->inUse)
		Com_Error(false, "R_RemoveDecalsFromWorld: scene is currently in use");

	if (!rg.world)
		Com_Error(false, "R_RemoveDecalsFromWorld: NULL world");

	if (!scene->decalList)
		return;		// No decals in this scene

	// Remove any decals from the world entity
	for (decal = scene->activeDecal.next; decal != &scene->activeDecal; decal = next){
		// Grab next now, so if the decal is freed we still have it
		next = decal->next;

		// Check if it belongs to the world entity
		if (decal->parentEntity != scene->worldEntity)
			continue;

		// Free it
		R_FreeDecal(scene, decal);
	}
}

/*
 ==================
 
 ==================
*/
void R_ProjectDecal (scene_t *scene, int entityHandle, const glqVec3 &origin, const glqVec3 &direction, float rotation, float size, float depth, int startTime, material_t *material){

}

/*
 ==================
 R_RemoveDecals
 ==================
*/
void R_RemoveDecals (scene_t *scene, int entityHandle){

	entity_t	*entity;
	decal_t		*decal, *next;

	if (scene->inUse)
		Com_Error(false, "R_RemoveDecals: scene is currently in use");

	if (entityHandle <= 0 || entityHandle > scene->maxEntities)
		Com_Error(false, "R_RemoveDecals: entityHandle out of range");

	entity = &scene->entityList[entityHandle - 1];

	if (!entity->active){
		Com_Printf(S_COLOR_YELLOW "R_RemoveDecals: entityHandle %i is not active\n", entityHandle);
		return;
	}

	if (entity->e.type != RE_MODEL)
		return;		// Not a model

	if (!scene->decalList)
		return;		// No decals in this scene

	// Remove any decals from this entity
	for (decal = scene->activeDecal.next; decal != &scene->activeDecal; decal = next){
		// Grab next now, so if the decal is freed we still have it
		next = decal->next;

		// Check if it belongs to this entity
		if (decal->parentEntity != entity)
			continue;

		// Free it
		R_FreeDecal(scene, decal);
	}
}